﻿using Serilog.Core;
using Serilog.Events;
using Serilog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using WatchDog.WatchItemManages;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Xml.Linq;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Concurrent;

namespace WatchDog.WinService
{
    internal class BackgroundJob
    {
        private static System.Timers.Timer _timer;
        private int _err = 0;

        public ILogger Logger { get; private set; }

        public WatchItemManage WatchManage { get; private set; }

        private readonly ConcurrentStack<long> stack = new ConcurrentStack<long>();

        private TimerHandler _task;
        public BackgroundJob(string strAssemblyDirPath)
        {

            Log.Logger = new LoggerConfiguration()
           //.MinimumLevel.Debug()
           .MinimumLevel.ControlledBy(Serilog.loggingLevelSwitch)
           .WriteTo.Sink(Serilog.Sink)
           .WriteTo.File(strAssemblyDirPath + "/Logs/server-.log",
           rollingInterval: RollingInterval.Day,
           retainedFileTimeLimit: TimeSpan.FromDays(7),
           //outputTemplate: "{HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
           fileSizeLimitBytes: 5242880)
           //.Filter.ByExcluding(e => (int)e.Level < _minimumLogLevel)
           .CreateLogger();

            Logger = Log.Logger;
            Serilog.StartSendLog();

            WatchManage = new WatchItemManage();

            int i = 0;
            _timer = new System.Timers.Timer(1000) { AutoReset = true };
            _timer.Elapsed += (sender, eventArgs) =>
            {
                i++;
                Log.Logger.Warning($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff")}");
                if (stack.IsEmpty)
                {
                    stack.Push(i);
                }
            };
        }

        public void Start()
        {
            Log.Logger.Information("正在启动服务...");
            Log.Logger.Debug($"开始 Timer");
            _err = 0;
            _timer.Start();

            _task = new TimerHandler(() =>
            {
                if (stack.TryPop(out var taskNo))
                {
                    //Log.Logger.Warning($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff")}  ----");

                    try
                    {
                        if (_err > 5)
                        {
                            Log.Logger.Debug($"定时器任务中发生错误次数已超过5次，已跳过");
                            return;
                        }

                        DelayedJobManager.BeforeAddOrUpdate(taskNo);

                        var items = WatchManage.GetAllWatchItems();
                        if (items.Any())
                        {
                            try
                            {
                                foreach (var item in items)
                                {
                                    if (item.AutoStart == true)
                                    {
                                        var runTime = ProcessHelper.GetRunningTotalMinutes(item.FilePath);
                                        if (runTime > 0)
                                        {
                                            Log.Logger.Debug($"程序{item.FileName},{item.FilePath}正在运行中...");
                                            if (item.ScheduledRestart > 0 && runTime > item.ScheduledRestart)
                                            {
                                                Log.Logger.Debug($"执行定时重启任务：程序{item.FileName}已连续运行{runTime}分钟，重启阀值为{item.ScheduledRestart}分钟。");
                                                //判断是否为服务程序，如果是则执行停止服务操作，否则执行关闭进程操作
                                                if (item.Type == 1)
                                                {
                                                    WindowsServiceManage.ServiceStop(item.Name);
                                                }
                                                else
                                                {
                                                    ProcessHelper.Stop(item.FilePath);
                                                }

                                            }
                                        }
                                        else
                                        {
                                            Log.Logger.Debug($"程序{item.FileName},{item.FilePath}未运行");

                                            if (item.DelayStart > 0)
                                            {
                                                Log.Logger.Debug($"延迟启动值为：{item.DelayStart} 秒，已加入计划任务");

                                                DelayedJobManager.AddOrUpdate(item, () =>
                                                {
                                                    Log.Logger.Debug($"延迟启动任务：正在完成对程序{item.FileName}的启动（延迟{item.DelayStart}秒）");
                                                    if (item.Type == 1)
                                                    {
                                                        if (!WindowsServiceManage.IsServiceExisted(item.Name))
                                                        {
                                                            WindowsServiceManage.InstallService(item.FilePath, item.Name, item.DisplayName);
                                                        }
                                                        WindowsServiceManage.ServiceRestart(item.Name);
                                                    }
                                                    else
                                                    {
                                                        ProcessHelper.Start(item.FilePath);
                                                    }

                                                });
                                                //AddDelayStartTask(item.DelayStart * 1000, item.FilePath);
                                            }
                                            else
                                            {
                                                Log.Logger.Debug($"正在启动...");
                                                if (item.Type == 1)
                                                {
                                                    if (!WindowsServiceManage.IsServiceExisted(item.Name))
                                                    {
                                                        WindowsServiceManage.InstallService(item.FilePath, item.Name, item.DisplayName);
                                                    }
                                                    WindowsServiceManage.ServiceRestart(item.Name);
                                                }
                                                else
                                                {
                                                    ProcessHelper.Start(item.FilePath);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                Log.Logger.Error(ex, "执行定时任务时发生错误");
                            }
                        }

                        DelayedJobManager.AfterAddOrUpdate();
                    }
                    catch (Exception ex)
                    {
                        _err += 1;
                        Logger.Error(ex, $"执行定时任务时出错：当前以错误 {_err} 次");
                    }
                }
                else
                {
                    Thread.Sleep(100);
                }
            });
        }

        public void Stop()
        {
            Log.Logger.Information("正在停止服务...");

            Log.Logger.Debug($"停止 Timer ");
            _timer.Stop();

            if (_task != null)
            {
                _task.Cancel();
            }

            DelayedJobManager.Clear();
        }

        public void Restart()
        {
            Stop();

            Log.Logger.Debug($"清理 Config Manage 缓存");
            WatchManage.ClearCache(); // 清除缓存，下次取数据时就会从数据库读取，达到刷新监控项的目的

            _err = 0;

            Start();
        }

    }

    public class TimerHandler
    {
        private readonly CancellationTokenSource cts1 = new();
        private readonly CancellationToken token = new();
        public TimerHandler(Action action)
        {
            token = cts1.Token;

            Task.Run(() =>
            {
                while (!token.IsCancellationRequested)
                {
                    action.Invoke();
                }
                IsCompleted = true;
            }, token);
        }

        public void Cancel()
        {
            cts1.Cancel();
        }

        public bool IsCompleted { get; private set; }
    }



    //BackgroundJob.Schedule(
    //() => Console.WriteLine("Delayed!"),
    //TimeSpan.FromDays(7));
}
